package dbPhase.hypeerweb;


/**
 * UpPointingNodeState is a state that represents a node in an UpPointing state.
 *
 * @see NodeState
 *
 * @pre singleton - UpPointingNodeState
 *
 *
 */
public class UpPointingNodeState extends NodeState {

	static UpPointingNodeState singleton;

	private UpPointingNodeState() {

	}

	static UpPointingNodeState getSingleton() {
		if (singleton == null ) {
			singleton = new UpPointingNodeState();
		}
		return singleton;
	}

	public static final int STATE_ID = 1;

	@Override
	public Node find(Node thisNode ) {
		//Determine the bigger of the fold and largest neighbor
		Node fold = Null_Node.getSingleton();
		if (thisNode.surrogateFold.getWebIdValue() > thisNode.fold.getWebIdValue()) {
			fold = thisNode.surrogateFold;
		}
		else {
			fold = thisNode.fold;
		}

		Node biggestNeighbor = thisNode.getBiggestUpPointer();

		if (fold.getWebIdValue() > biggestNeighbor.getWebIdValue()) {
			return fold.nodeState.find(fold);
		}
		else {
			return biggestNeighbor.nodeState.find(biggestNeighbor);
		}
	}


	//Up: Find biggest uppointer, if uppointer.parent.id is greater than lb,
	//	  then call biggestuppointer.search(biggestuppointer.child.id, ub, newnode)
	//    otherwise, if lb cant change: using smallest neghbor that is childless as ub, call smallchildlessneghibor.serch(lb, ub, newnode)


	@Override
	public Node search(int lb, int ub, Node thisNode ) {
		if (ub == -1) {
			ub = thisNode.getWebIdValue();
		}
		if ((ub - lb == 1) && thisNode.getWebId().getValue() == ub) {
			return thisNode;
		}
		else {

			Node biggest = thisNode.getBiggestUpPointer();
			Node biggestUpsParent = biggest.getSmallestNeighbor();

			if (biggestUpsParent.webId.getValue() > lb || lb > ub) {
				return biggest.nodeState.search(biggestUpsParent.webId.getValue(), ub, biggest);
			}
			else {
				Node smallestchildlessneighbor = thisNode.getSmallestUpPointer();
				for (Node n: thisNode.neighbors) {
					if (n.getWebId().getValue() < smallestchildlessneighbor.getWebIdValue()) {
						if (n.upPointers.size() != 0) { //n is childless
							smallestchildlessneighbor = n;
						}
					}
				}

				if (smallestchildlessneighbor.getWebIdValue() < ub) {
					ub = smallestchildlessneighbor.getWebIdValue();
				}
				return smallestchildlessneighbor.nodeState.search(lb, ub, smallestchildlessneighbor);
			}
		}
	}
	@Override
	public int getStateId() {

		return STATE_ID;
	}
	@Override
	public String toString() {
		return "Up Pointing Node State";
	}

	@Override
	public Node findDP(Node thisNode) {
		// TODO Auto-generated method stub
		//Determine the bigger of the fold and largest neighbor
		Node fold = Null_Node.getSingleton();
		if (thisNode.surrogateFold.getWebId().getValue() > thisNode.fold.getWebId().getValue()) {
			fold = thisNode.surrogateFold;
		}
		else {
			fold = thisNode.fold;
		}
		Node biggestNeighbor = thisNode.getBiggestUpPointer();

		if (fold.getWebId().getValue() > biggestNeighbor.getWebId().getValue()) {
			return fold.nodeState.findDP( fold);
		}
		else {
			return biggestNeighbor.nodeState.findDP(biggestNeighbor);
		}
	}

	@Override
	public Node searchDP(int lb, int ub,
			Node thisNode) {
		if ((ub - lb == 1) && thisNode.getWebId().getValue() == ub) {
			Node biggest = thisNode.getBiggestUpPointer();
			return biggest.nodeState.searchDP(lb, ub, biggest);
		}
		else {
			Node biggest = thisNode.getBiggestUpPointer();
			Node biggestUpsParent = biggest.getSmallestNeighbor();

			if (biggestUpsParent.webId.getValue() > lb) {
				return biggest.nodeState.searchDP(biggestUpsParent.webId.getValue(), ub, biggest);
			}
			else {
				//using smallest neghbor that is childless as ub, call smallchildlessneghibor.serch(lb, ub, newnode)
				Node smallestchildlessneighbor = thisNode;

				for (Node n: thisNode.neighbors) {
					if (n.getWebId().getValue() < smallestchildlessneighbor.webId.getValue()) {
						if (n.upPointers.size() != 0) { //n is childless
							smallestchildlessneighbor = n;
						}
					}
				}
				return smallestchildlessneighbor.nodeState.searchDP(lb, smallestchildlessneighbor.getWebIdValue(), smallestchildlessneighbor);
			}
		}
	}
}
